"""
类中的方法：普通方法，类方法，静态方法，魔术方法

普通方法：
    def 方法名 （self,参数1，参数2...）
类方法:
    1. 定义需要依赖装饰器 @classmethod
    2. 类方法中参数不是一个对象，而是类
    3. 类方法中只可以使用类属性
    4. 类方法中也不能调用普通方法
    @classmethod
    def test(cls):
        pass
    类方法作用：
        只能访问类属性和类方法，所以可以在对象创建之前，如果需要完成一些动作（功能）
静态方法：
1. 需要装饰器 @staticmethod
2. 只能访问类的属性和方法，对象的无法访问
3. 加载时机和类方法一致
@staticmethod
def test():
    pass
    总结静态方法和类方法：
        不同：
            1. 装饰器不同
            2. 类方法是有参数的，静态方法没有参数
        相同：
            1. 只能访问类的属性和方法，对象的是无法访问的
            2. 都可以通过类名调用访问
            3. 都可以在创建对象之前使用，因为是不依赖于对象

 魔术方法：
 def __new__(cls):实例化时候触发,了解（作用就是申请内存，开辟空间），返回的是一个地址，这一步完成了下一步init里面的self参数才有值[了解]

 def __init__(self): 初始化对象的时候触发[重要]

__call()__ :将对象被当作函数调用的时候被执行
 __del()__ : [了解]
    1. 对象赋值
        p=Person()
        p1=p
        说明：p和p1共同指向同一个地址
    2. 删除地址的引用
        del p1 删除p1对该地址的引用
    3. 查看对地址的引用次数：
        import sys
        sys.getrefcount(p) #查看对象的引用次数
    4. 当一块空间没有了地址引用，默认执行__del__
        python解释器在代码执行完毕后也会调用__del__方法进行回收对象

__str()__ ：打印对象时候调用的方法[重要]
"""
import sys


class parent:
    username = "高嘉银"
    phone = "18883337187"
    __age = 18  # 私有属性

    # 魔术方法
    def __new__(cls, *args, **kwargs):
        print("--------new------")
        position = object.__new__(cls)  # 申请内存，返回对象的内存地址，有了这一步，后面的init初始化中的self变量才有值
        print(position)
        return position

    def __init__(self, username, phone):  # init 初始化
        self.username = username
        self.phone = phone

    def __call__(self, *args, **kwargs):  # 对象当成函数使用时候被调用
        print("call---------", args)

    def __del__(self):
        print("对象被删除时候调用------------")

    def __str__(self):
        return self.username + ":" + self.phone

    # 对象方法，普通方法
    def call(self):
        print(self.phone)

    # 类方法
    @classmethod
    def test(cls):
        cls.__age = 20
        print(cls.username)
        print("类方法")

    # 静态方法，无需要参数cls,self
    @staticmethod
    def static_test(a):
        print("静态方法。")
        print(a)
        print(parent.username)  # 静态方法访问类属性需要使用类名访问

    pass


#
# parent.test()
# parent.static_test(3)
# p = parent("廖立晴", "15213794066")
# p.call()
# p.test()

p = parent("廖立晴", "15213794066")
print(p)
p("高嘉银")  # 将对象当函数调用时候会调用__call()__方法
p1 = p
p2 = p
print(sys.getrefcount(p))  # 查看p对象被引用的次数
del p1
print(sys.getrefcount(p))
del p2
print(sys.getrefcount(p))
del p  # 该对象的引用为0的时候才会调用__del()__方法，上面删除的p1,p2引用不会调用
